package com.rwx.beanfactory;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

public class Test01BeanFactory {

    public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        //beanFactory 先根据bean的定义建造出bean

        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Config.class).setScope("singleton").getBeanDefinition();
        beanFactory.registerBeanDefinition("config",beanDefinition);

//        for (String name : beanFactory.getBeanDefinitionNames()) {
//            System.out.println(name);
//        }

        //beanFactory 后处理器主要功能 补充Bean的定义，有了定义
        AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);

        //beanFactory生成bean后需要取出才能使用，这里使用BeanFactoryPostProcessor进行解析
        beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().stream().forEach(beanFactoryPostProcessor -> {
            beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
        });

        //Bean 后处理器 针对bean的生命周期各个阶段提供扩展
        beanFactory.getBeansOfType(BeanPostProcessor.class).values().stream().forEach(beanFactory::addBeanPostProcessor);

        for (String name : beanFactory.getBeanDefinitionNames()) {
            System.out.println(name);
        }


        //beanFactory.getBean 调用时才去实例化bean
        //单例情况下需要先提前实例化
        beanFactory.preInstantiateSingletons();

        //这里是beanFactory取出bean
        //此时bean2是null，因为还没有依赖注入的功能，依赖注入的功能还没加载，
        //依赖注入的功能也是根据后处理器进行生成
        System.out.println(beanFactory.getBean(Bean1.class).getBean2());

    /**
     a.beanFactory 不会做的事
     1.不会主动调用BeanFactory后处理器
     2.不会主动添加Bean处理器
     3.不会主动初始化单例
     4.不会解析beanFactory 还不会解析${} #{}

     以上的几点 ApplicationContext全都做了优化

     b.bean后处理器会有排序的逻辑

     @Autowired 会先根据类型进行注入，如果有多个同类型的bean则会根据bean的name优先选择

     @Autowired和@Reource(name="bean4") 两个都添加的话，会优先按照@Autowired选择bean
     原因：Autowired的后处理器优先级高，先添加的，先按Autowired解析bean
     不同后处理器都实现了Order接口，spring中后处理器根据order字段进行排序

    */



    }

    @Configuration
    static class Config {
        @Bean
        public Bean1 bean1() {
            return new Bean1();
        }

        @Bean
        public Bean2 bean2() {
            return new Bean2();
        }
    }


    @Slf4j
    static class Bean1 {

        public Bean1() {
            log.info("构造 Bean1()");
        }

        @Autowired
        private Bean2 bean2;

        public Bean2 getBean2() {
            return bean2;
        }

    }

    @Slf4j
    static class Bean2 {
        public Bean2() {
            log.info("构造 Bean2()");
        }
    }


}
